home *** CD-ROM | disk | FTP | other *** search
/ MaxiMac 2000 December / MaxiMac 109.iso / Macworld on CD n°109 / Applications (Mac OS X PB) / MacOSX ScreenSavers / Source Code / Pipes / pipes.c < prev   
Encoding:
C/C++ Source or Header  |  2000-10-02  |  25.9 KB  |  959 lines  |  [????/????]

  1. /* -*- Mode: C; tab-width: 4 -*- */
  2. /* pipes --- 3D selfbuiding pipe system */
  3.  
  4. #if !defined( lint ) && !defined( SABER )
  5. static const char sccsid[] = "@(#)pipes.c    4.07 97/11/24 xlockmore";
  6.  
  7. #endif
  8.  
  9. /*-
  10.  * Permission to use, copy, modify, and distribute this software and its
  11.  * documentation for any purpose and without fee is hereby granted,
  12.  * provided that the above copyright notice appear in all copies and that
  13.  * both that copyright notice and this permission notice appear in
  14.  * supporting documentation.
  15.  *
  16.  * This file is provided AS IS with no warranties of any kind.  The author
  17.  * shall have no liability with respect to the infringement of copyrights,
  18.  * trade secrets or any patents by this file or any part thereof.  In no
  19.  * event will the author be liable for any lost revenue or profits or
  20.  * other special, indirect and consequential damages.
  21.  *
  22.  * This program was inspired on a WindowsNT(R)'s screen saver. It was written 
  23.  * from scratch and it was not based on any other source code.
  24.  *
  25.  * ==========================================================================
  26.  * The routine myElbow is derivated from the doughnut routine from the OpenGL
  27.  * library (more especifically the Mesaaux library) written by Brian Paul.
  28.  * ==========================================================================
  29.  *
  30.  * Thanks goes to Brian Paul for making it possible and inexpensive to use
  31.  * OpenGL at home.
  32.  *
  33.  * Since I'm not a native English speaker, my apologies for any grammatical
  34.  * mistake.
  35.  *
  36.  * My e-mail address is
  37.  * m-vianna@usa.net
  38.  * Marcelo F. Vianna (Apr-09-1997)
  39.  *
  40.  * Revision History:
  41.  * 29-Apr-97: Factory equipment by Ed Mackey.  Productive day today, eh?
  42.  * 29-Apr-97: Less tight turns Jeff Epler <jepler@inetnebr.com>
  43.  * 29-Apr-97: Efficiency speed-ups by Marcelo F. Vianna
  44.  */
  45.  
  46. /*-
  47.  * due to a Bug/feature in VMS X11/Intrinsic.h has to be placed before xlock.
  48.  * otherwise caddr_t is not defined correctly
  49.  */
  50.  
  51. /*
  52. #include <X11/Intrinsic.h>
  53.  
  54. #ifdef STANDALONE
  55. # define PROGCLASS                    "Pipes"
  56. # define HACK_INIT                    init_pipes
  57. # define HACK_DRAW                    draw_pipes
  58. # define pipes_opts                    xlockmore_opts
  59. # define DEFAULTS    "*delay:        100     \n"            \
  60.                     "*count:        2       \n"            \
  61.                     "*cycles:        5       \n"            \
  62.                     "*size:            500     \n"            \
  63.                     "*fisheye:        True    \n"            \
  64.                     "*tightturns:    False   \n"            \
  65.                     "*rotatepipes:    True    \n"            \
  66.                     "*noBuffer:        True    \n"
  67. # include "xlockmore.h"                
  68. #else 
  69. # include "xlock.h"                
  70. #endif 
  71.  
  72. #ifdef USE_GL
  73.  
  74. */
  75.  
  76. #include <OpenGL/glu.h>
  77. #include "buildlwo.h"
  78.  
  79. #define DEF_FACTORY     "2"
  80. #define DEF_FISHEYE     "True"
  81. #define DEF_TIGHTTURNS  "False"
  82. #define DEF_ROTATEPIPES "True"
  83. #define NofSysTypes     3
  84. #define Bool int
  85.  
  86. extern int NRAND_PIPES(int foo);
  87.  
  88.  
  89. static int  factory;
  90. static Bool fisheye, tightturns, rotatepipes;
  91.  
  92. /*
  93. static XrmOptionDescRec opts[] =
  94. {
  95.     {"-factory", ".pipes.factory", XrmoptionSepArg, (caddr_t) NULL},
  96.     {"-fisheye", ".pipes.fisheye", XrmoptionNoArg, (caddr_t) "on"},
  97.     {"+fisheye", ".pipes.fisheye", XrmoptionNoArg, (caddr_t) "off"},
  98.     {"-tightturns", ".pipes.tightturns", XrmoptionNoArg, (caddr_t) "on"},
  99.     {"+tightturns", ".pipes.tightturns", XrmoptionNoArg, (caddr_t) "off"},
  100.       {"-rotatepipes", ".pipes.rotatepipes", XrmoptionNoArg, (caddr_t) "on"},
  101.       {"+rotatepipes", ".pipes.rotatepipes", XrmoptionNoArg, (caddr_t) "off"}
  102. };
  103. static argtype vars[] =
  104. {
  105.     {(caddr_t *) & factory, "factory", "Factory", DEF_FACTORY, t_Int},
  106.     {(caddr_t *) & fisheye, "fisheye", "Fisheye", DEF_FISHEYE, t_Bool},
  107.     {(caddr_t *) & tightturns, "tightturns", "Tightturns", DEF_TIGHTTURNS, t_Bool},
  108.     {(caddr_t *) & rotatepipes, "rotatepipes", "Rotatepipes", DEF_ROTATEPIPES, t_Bool}
  109. };
  110. static OptionStruct desc[] =
  111. {
  112.     {"-factory num", "how much extra equipment in pipes (0 for none)"},
  113.     {"-/+fisheye", "turn on/off zoomed-in view of pipes"},
  114.     {"-/+tightturns", "turn on/off tight turns"},
  115.     {"-/+rotatepipes", "turn on/off pipe system rotation per screenful"}
  116. };
  117.  
  118. ModeSpecOpt pipes_opts =
  119. {sizeof opts / sizeof opts[0], opts, sizeof vars / sizeof vars[0], vars, desc};
  120.  
  121. #ifdef USE_MODULES
  122. ModStruct   pipes_description =
  123. {"pipes", "init_pipes", "draw_pipes", "release_pipes",
  124. #if defined( MESA ) && defined( SLOW )
  125.  "draw_pipes",
  126. #else
  127.  "change_pipes",
  128. #endif
  129.  "change_pipes", NULL, &pipes_opts,
  130.  1000, 2, 5, 500, 4, 1.0, "",
  131.  "Shows a selfbuilding pipe system", 0, NULL};
  132.  
  133. #endif
  134.  
  135. */
  136.  
  137. #define Scale4Window               0.1
  138. #define Scale4Iconic               0.07
  139.  
  140. #define one_third                  0.3333333333333333333
  141.  
  142. #define dirNone -1
  143. #define dirUP 0
  144. #define dirDOWN 1
  145. #define dirLEFT 2
  146. #define dirRIGHT 3
  147. #define dirNEAR 4
  148. #define dirFAR 5
  149.  
  150. #define HCELLS 33
  151. #define VCELLS 25
  152. #define DEFINEDCOLORS 7
  153. #define elbowradius 0.5
  154.  
  155. /*************************************************************************/
  156.  
  157.     GLint       WindH, WindW;
  158.     int         Cells[HCELLS][VCELLS][HCELLS];
  159.     int         usedcolors[DEFINEDCOLORS];
  160.     int         directions[6];
  161.     int         ndirections;
  162.     int         nowdir, olddir;
  163.     int         system_number;
  164.     int         counter;
  165.     int         PX, PY, PZ;
  166.     int         number_of_systems;
  167.     int         system_type;
  168.     int         system_length;
  169.     int         turncounter;
  170.     float      *system_color;
  171.     GLfloat     initial_rotation;
  172.     GLuint      valve, bolts, betweenbolts, elbowbolts, elbowcoins;
  173.     GLuint      guagehead, guageface, guagedial, guageconnector;
  174. int            isMono = 0;
  175. int            isWireframe = 0;
  176.  
  177.  
  178. extern struct lwo LWO_BigValve, LWO_PipeBetweenBolts, LWO_Bolts3D;
  179. extern struct lwo LWO_GuageHead, LWO_GuageFace, LWO_GuageDial, LWO_GuageConnector;
  180. extern struct lwo LWO_ElbowBolts, LWO_ElbowCoins;
  181.  
  182. static float pipe_shininess[] =
  183. {60.0};
  184. static float pipe_specular[] =
  185. {0.7, 0.7, 0.7, 1.0};
  186. static float ambient_pipe0[] =
  187. {0.4, 0.4, 0.4, 1.0};
  188. static float diffuse_pipe0[] =
  189. {1.0, 1.0, 1.0, 1.0};
  190. static float ambient_pipe1[] =
  191. {0.2, 0.2, 0.2, 1.0};
  192. static float diffuse_pipe1[] =
  193. {0.5, 0.5, 0.5, 1.0};
  194. static float position_pipe0[] =
  195. {1.0, 1.0, 1.0, 0.0};
  196. static float position_pipe1[] =
  197. {-1.0, -1.0, 1.0, 0.0};
  198. static float lmodel_ambient_pipe[] =
  199. {0.5, 0.5, 0.5, 1.0};
  200. static float lmodel_twoside_pipe[] =
  201. {GL_TRUE};
  202.  
  203. static float MaterialRed[] =
  204. {0.7, 0.0, 0.0, 1.0};
  205. static float MaterialGreen[] =
  206. {0.1, 0.5, 0.2, 1.0};
  207. static float MaterialBlue[] =
  208. {0.0, 0.0, 0.7, 1.0};
  209. static float MaterialCyan[] =
  210. {0.2, 0.5, 0.7, 1.0};
  211. static float MaterialYellow[] =
  212. {0.7, 0.7, 0.0, 1.0};
  213. static float MaterialMagenta[] =
  214. {0.6, 0.2, 0.5, 1.0};
  215. static float MaterialWhite[] =
  216. {0.7, 0.7, 0.7, 1.0};
  217. static float MaterialGray[] =
  218. {0.2, 0.2, 0.2, 1.0};
  219.  
  220. static void
  221. MakeTube(int direction)
  222. {
  223.     float       an;
  224.     float       SINan_3, COSan_3;
  225.  
  226.     /*dirUP    = 00000000 */
  227.     /*dirDOWN  = 00000001 */
  228.     /*dirLEFT  = 00000010 */
  229.     /*dirRIGHT = 00000011 */
  230.     /*dirNEAR  = 00000100 */
  231.     /*dirFAR   = 00000101 */
  232.  
  233.     if (!(direction & 4)) {
  234.         glRotatef(90.0, (direction & 2) ? 0.0 : 1.0,
  235.               (direction & 2) ? 1.0 : 0.0, 0.0);
  236.     }
  237.     glBegin(GL_QUAD_STRIP);
  238.     for (an = 0.0; an <= 2.0 * M_PI; an += M_PI / 12.0) {
  239.         glNormal3f((COSan_3 = cos(an) / 3.0), (SINan_3 = sin(an) / 3.0), 0.0);
  240.         glVertex3f(COSan_3, SINan_3, one_third);
  241.         glVertex3f(COSan_3, SINan_3, -one_third);
  242.     }
  243.     glEnd();
  244. }
  245.  
  246. static void
  247. mySphere(float radius)
  248. {
  249.     GLUquadricObj *quadObj;
  250.  
  251.     quadObj = gluNewQuadric();
  252.     gluQuadricDrawStyle(quadObj, (GLenum) GLU_FILL);
  253.     gluSphere(quadObj, radius, 16, 16);
  254.     gluDeleteQuadric(quadObj);
  255. }
  256.  
  257. static void
  258. myElbow(int bolted)
  259. {
  260. #define nsides 25
  261. #define rings 25
  262. #define r one_third
  263. #define R one_third
  264.  
  265.     int         i, j;
  266.     GLfloat     p0[3], p1[3], p2[3], p3[3];
  267.     GLfloat     n0[3], n1[3], n2[3], n3[3];
  268.     GLfloat     COSphi, COSphi1, COStheta, COStheta1;
  269.     GLfloat     _SINtheta, _SINtheta1;
  270.  
  271.     for (i = 0; i <= rings / 4; i++) {
  272.         GLfloat     theta, theta1;
  273.  
  274.         theta = (GLfloat) i *2.0 * M_PI / rings;
  275.  
  276.         theta1 = (GLfloat) (i + 1) * 2.0 * M_PI / rings;
  277.         for (j = 0; j < nsides; j++) {
  278.             GLfloat     phi, phi1;
  279.  
  280.             phi = (GLfloat) j *2.0 * M_PI / nsides;
  281.  
  282.             phi1 = (GLfloat) (j + 1) * 2.0 * M_PI / nsides;
  283.  
  284.             p0[0] = (COStheta = cos(theta)) * (R + r * (COSphi = cos(phi)));
  285.             p0[1] = (_SINtheta = -sin(theta)) * (R + r * COSphi);
  286.  
  287.             p1[0] = (COStheta1 = cos(theta1)) * (R + r * COSphi);
  288.             p1[1] = (_SINtheta1 = -sin(theta1)) * (R + r * COSphi);
  289.  
  290.             p2[0] = COStheta1 * (R + r * (COSphi1 = cos(phi1)));
  291.             p2[1] = _SINtheta1 * (R + r * COSphi1);
  292.  
  293.             p3[0] = COStheta * (R + r * COSphi1);
  294.             p3[1] = _SINtheta * (R + r * COSphi1);
  295.  
  296.             n0[0] = COStheta * COSphi;
  297.             n0[1] = _SINtheta * COSphi;
  298.  
  299.             n1[0] = COStheta1 * COSphi;
  300.             n1[1] = _SINtheta1 * COSphi;
  301.  
  302.             n2[0] = COStheta1 * COSphi1;
  303.             n2[1] = _SINtheta1 * COSphi1;
  304.  
  305.             n3[0] = COStheta * COSphi1;
  306.             n3[1] = _SINtheta * COSphi1;
  307.  
  308.             p0[2] = p1[2] = r * (n0[2] = n1[2] = sin(phi));
  309.             p2[2] = p3[2] = r * (n2[2] = n3[2] = sin(phi1));
  310.  
  311.             glBegin(GL_QUADS);
  312.             glNormal3fv(n3);
  313.             glVertex3fv(p3);
  314.             glNormal3fv(n2);
  315.             glVertex3fv(p2);
  316.             glNormal3fv(n1);
  317.             glVertex3fv(p1);
  318.             glNormal3fv(n0);
  319.             glVertex3fv(p0);
  320.             glEnd();
  321.         }
  322.     }
  323.  
  324.     if (factory > 0 && bolted) {
  325.         /* Bolt the elbow onto the pipe system */
  326.         glFrontFace(GL_CW);
  327.         glPushMatrix();
  328.         glRotatef(90.0, 0.0, 0.0, -1.0);
  329.         glRotatef(90.0, 0.0, 1.0, 0.0);
  330.         glTranslatef(0.0, one_third, one_third);
  331.         glCallList(elbowcoins);
  332.         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
  333.         glCallList(elbowbolts);
  334.         glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, system_color);
  335.         glPopMatrix();
  336.         glFrontFace(GL_CCW);
  337.     }
  338. #undef r
  339. #undef R
  340. #undef nsides
  341. #undef rings
  342. }
  343.  
  344. static void
  345. FindNeighbors()
  346. {
  347.  
  348.     ndirections = 0;
  349.     directions[dirUP] = (!Cells[PX][PY + 1][PZ]) ? 1 : 0;
  350.     ndirections += directions[dirUP];
  351.     directions[dirDOWN] = (!Cells[PX][PY - 1][PZ]) ? 1 : 0;
  352.     ndirections += directions[dirDOWN];
  353.     directions[dirLEFT] = (!Cells[PX - 1][PY][PZ]) ? 1 : 0;
  354.     ndirections += directions[dirLEFT];
  355.     directions[dirRIGHT] = (!Cells[PX + 1][PY][PZ]) ? 1 : 0;
  356.     ndirections += directions[dirRIGHT];
  357.     directions[dirFAR] = (!Cells[PX][PY][PZ - 1]) ? 1 : 0;
  358.     ndirections += directions[dirFAR];
  359.     directions[dirNEAR] = (!Cells[PX][PY][PZ + 1]) ? 1 : 0;
  360.     ndirections += directions[dirNEAR];
  361. }
  362.  
  363. static int
  364. SelectNeighbor()
  365. {
  366.     int         dirlist[6];
  367.     int         i, j;
  368.  
  369.     for (i = 0, j = 0; i < 6; i++) {
  370.         if (directions[i]) {
  371.             dirlist[j] = i;
  372.             j++;
  373.         }
  374.     }
  375.  
  376.     return dirlist[NRAND_PIPES(ndirections)];
  377. }
  378.  
  379. static void
  380. MakeValve(int newdir)
  381. {
  382.     /* There is a glPopMatrix() right after this subroutine returns. */
  383.     switch (newdir) {
  384.         case dirUP:
  385.         case dirDOWN:
  386.             glRotatef(90.0, 1.0, 0.0, 0.0);
  387.             glRotatef(NRAND_PIPES(3) * 90.0, 0.0, 0.0, 1.0);
  388.             break;
  389.         case dirLEFT:
  390.         case dirRIGHT:
  391.             glRotatef(90.0, 0.0, -1.0, 0.0);
  392.             glRotatef((NRAND_PIPES(3) * 90.0) - 90.0, 0.0, 0.0, 1.0);
  393.             break;
  394.         case dirNEAR:
  395.         case dirFAR:
  396.             glRotatef(NRAND_PIPES(4) * 90.0, 0.0, 0.0, 1.0);
  397.             break;
  398.     }
  399.     glFrontFace(GL_CW);
  400.     glCallList(betweenbolts);
  401.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
  402.     glCallList(bolts);
  403.     if (!isMono) {
  404.         if (system_color == MaterialRed) {
  405.             glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND_PIPES(2) ? MaterialYellow : MaterialBlue);
  406.         } else if (system_color == MaterialBlue) {
  407.             glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND_PIPES(2) ? MaterialRed : MaterialYellow);
  408.         } else if (system_color == MaterialYellow) {
  409.             glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, NRAND_PIPES(2) ? MaterialBlue : MaterialRed);
  410.         } else {
  411.             switch ((NRAND_PIPES(3))) {
  412.                 case 0:
  413.                     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialRed);
  414.                     break;
  415.                 case 1:
  416.                     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialBlue);
  417.                     break;
  418.                 case 2:
  419.                     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialYellow);
  420.             }
  421.         }
  422.     }
  423.     glRotatef((GLfloat) (NRAND_PIPES(90)), 1.0, 0.0, 0.0);
  424.     glCallList(valve);
  425.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, system_color);
  426.     glFrontFace(GL_CCW);
  427. }
  428.  
  429. static int
  430. MakeGuage(int newdir)
  431. {
  432.  
  433.     /* Can't have a guage on a vertical pipe. */
  434.     if ((newdir == dirUP) || (newdir == dirDOWN))
  435.         return (0);
  436.  
  437.     /* Is there space above this pipe for a guage? */
  438.     if (!directions[dirUP])
  439.         return (0);
  440.  
  441.     /* Yes!  Mark the space as used. */
  442.     Cells[PX][PY + 1][PZ] = 1;
  443.  
  444.     glFrontFace(GL_CW);
  445.     glPushMatrix();
  446.     if ((newdir == dirLEFT) || (newdir == dirRIGHT))
  447.         glRotatef(90.0, 0.0, 1.0, 0.0);
  448.     glCallList(betweenbolts);
  449.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialGray);
  450.     glCallList(bolts);
  451.     glPopMatrix();
  452.  
  453.     glCallList(guageconnector);
  454.     glPushMatrix();
  455.     glTranslatef(0.0, 1.33333, 0.0);
  456.     /* Do not change the above to 1 + ONE_THIRD, because */
  457.     /* the object really is centered on 1.3333300000. */
  458.     glRotatef(NRAND_PIPES(270) + 45.0, 0.0, 0.0, -1.0);
  459.     /* Random rotation for the dial.  I love it. */
  460.     glCallList(guagedial);
  461.     glPopMatrix();
  462.  
  463.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, system_color);
  464.     glCallList(guagehead);
  465.  
  466.     /* GuageFace is drawn last, in case of low-res depth buffers. */
  467.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, MaterialWhite);
  468.     glCallList(guageface);
  469.  
  470.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, system_color);
  471.     glFrontFace(GL_CCW);
  472.  
  473.     return (1);
  474. }
  475.  
  476. static void
  477. MakeShape(int newdir)
  478. {
  479.     switch (NRAND_PIPES(2)) {
  480.         case 1:
  481.             if (!MakeGuage(newdir))
  482.                 MakeTube(newdir);
  483.             break;
  484.         default:
  485.             MakeValve(newdir);
  486.             break;
  487.     }
  488. }
  489.  
  490. static void
  491. reshape_pipes(int width, int height)
  492. {
  493.  
  494.     glViewport(0, 0, WindW = (GLint) width, WindH = (GLint) height);
  495.     glMatrixMode(GL_PROJECTION);
  496.     glLoadIdentity();
  497.     /*glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 15.0); */
  498.     gluPerspective(65.0, (GLfloat) width / (GLfloat) height, 0.1, 20.0);
  499.     glMatrixMode(GL_MODELVIEW);
  500. }
  501.  
  502. static void
  503. pinit(int zera)
  504. {
  505.     int         X, Y, Z;
  506.  
  507.     glClearDepth(1.0);
  508.     glClearColor(0.0, 0.0, 0.0, 1.0);
  509.     glColor3f(1.0, 1.0, 1.0);
  510.  
  511.     glLightfv(GL_LIGHT0, GL_AMBIENT, ambient_pipe0);
  512.     glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse_pipe0);
  513.     glLightfv(GL_LIGHT0, GL_POSITION, position_pipe0);
  514.     glLightfv(GL_LIGHT1, GL_AMBIENT, ambient_pipe1);
  515.     glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse_pipe1);
  516.     glLightfv(GL_LIGHT1, GL_POSITION, position_pipe1);
  517.     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient_pipe);
  518.     glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside_pipe);
  519.     glEnable(GL_LIGHTING);
  520.     glEnable(GL_LIGHT0);
  521.     glEnable(GL_LIGHT1);
  522.     glEnable(GL_DEPTH_TEST);
  523.     glEnable(GL_NORMALIZE);
  524.     glEnable(GL_CULL_FACE);
  525.  
  526.     glShadeModel(GL_SMOOTH);
  527.     glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, pipe_shininess);
  528.     glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, pipe_specular);
  529.  
  530.     if (zera) {
  531.         system_number = 1;
  532.         glDrawBuffer(GL_FRONT_AND_BACK);
  533.         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  534.         (void) memset(Cells, 0, sizeof (Cells));
  535.         for (X = 0; X < HCELLS; X++) {
  536.             for (Y = 0; Y < VCELLS; Y++) {
  537.                 Cells[X][Y][0] = 1;
  538.                 Cells[X][Y][HCELLS - 1] = 1;
  539.                 Cells[0][Y][X] = 1;
  540.                 Cells[HCELLS - 1][Y][X] = 1;
  541.             }
  542.         }
  543.         for (X = 0; X < HCELLS; X++) {
  544.             for (Z = 0; Z < HCELLS; Z++) {
  545.                 Cells[X][0][Z] = 1;
  546.                 Cells[X][VCELLS - 1][Z] = 1;
  547.             }
  548.         }
  549.         (void) memset(usedcolors, 0, sizeof (usedcolors));
  550.         if ((initial_rotation += 10.0) > 45.0) {
  551.             initial_rotation -= 90.0;
  552.         }
  553.     }
  554.     counter = 0;
  555.     turncounter = 0;
  556.  
  557.     if (!isMono) {
  558.         int         collist[DEFINEDCOLORS];
  559.         int         i, j, lower = 1000;
  560.  
  561.         /* Avoid repeating colors on the same screen unless necessary */
  562.         for (i = 0; i < DEFINEDCOLORS; i++) {
  563.             if (lower > usedcolors[i])
  564.                 lower = usedcolors[i];
  565.         }
  566.         for (i = 0, j = 0; i < DEFINEDCOLORS; i++) {
  567.             if (usedcolors[i] == lower) {
  568.                 collist[j] = i;
  569.                 j++;
  570.             }
  571.         }
  572.         i = collist[NRAND_PIPES(j)];
  573.         usedcolors[i]++;
  574.         switch (i) {
  575.             case 0:
  576.                 system_color = MaterialRed;
  577.                 break;
  578.             case 1:
  579.                 system_color = MaterialGreen;
  580.                 break;
  581.             case 2:
  582.                 system_color = MaterialBlue;
  583.                 break;
  584.             case 3:
  585.                 system_color = MaterialCyan;
  586.                 break;
  587.             case 4:
  588.                 system_color = MaterialYellow;
  589.                 break;
  590.             case 5:
  591.                 system_color = MaterialMagenta;
  592.                 break;
  593.             case 6:
  594.                 system_color = MaterialWhite;
  595.                 break;
  596.         }
  597.     } else {
  598.         system_color = MaterialGray;
  599.     }
  600.  
  601.     do {
  602.         PX = NRAND_PIPES((HCELLS - 1)) + 1;
  603.         PY = NRAND_PIPES((VCELLS - 1)) + 1;
  604.         PZ = NRAND_PIPES((HCELLS - 1)) + 1;
  605.     } while (Cells[PX][PY][PZ] ||
  606.          (Cells[PX + 1][PY][PZ] && Cells[PX - 1][PY][PZ] &&
  607.           Cells[PX][PY + 1][PZ] && Cells[PX][PY - 1][PZ] &&
  608.           Cells[PX][PY][PZ + 1] && Cells[PX][PY][PZ - 1]));
  609.     Cells[PX][PY][PZ] = 1;
  610.     olddir = dirNone;
  611.  
  612.     FindNeighbors();
  613.  
  614.     nowdir = SelectNeighbor();
  615. }
  616.  
  617. void
  618. init_pipes()
  619. {
  620.  
  621.         reshape_pipes(WindW, WindH);
  622.         if (rotatepipes)
  623.           initial_rotation = NRAND_PIPES(180); /* jwz */
  624.         else
  625.           initial_rotation = -10.0;
  626.         pinit(1);
  627.  
  628.         if (factory > 0) {
  629.             valve = BuildLWO(isWireframe, &LWO_BigValve);
  630.             bolts = BuildLWO(isWireframe, &LWO_Bolts3D);
  631.             betweenbolts = BuildLWO(isWireframe, &LWO_PipeBetweenBolts);
  632.  
  633.             elbowbolts = BuildLWO(isWireframe, &LWO_ElbowBolts);
  634.             elbowcoins = BuildLWO(isWireframe, &LWO_ElbowCoins);
  635.  
  636.             guagehead = BuildLWO(isWireframe, &LWO_GuageHead);
  637.             guageface = BuildLWO(isWireframe, &LWO_GuageFace);
  638.             guagedial = BuildLWO(isWireframe, &LWO_GuageDial);
  639.             guageconnector = BuildLWO(isWireframe, &LWO_GuageConnector);
  640.         }
  641.         /* else they are all 0, thanks to calloc(). */
  642.  
  643.             system_type = NRAND_PIPES(NofSysTypes) + 1;
  644.  
  645.             number_of_systems = 5;
  646.  
  647.             system_length = 1000;
  648. }
  649.  
  650. void
  651. draw_pipes()
  652. {
  653.  
  654.     int         newdir;
  655.     int         OPX, OPY, OPZ;
  656.  
  657.     //glDrawBuffer(GL_FRONT);
  658.     glDrawBuffer(GL_BACK);
  659.     glPushMatrix();
  660.  
  661.     glTranslatef(0.0, 0.0, fisheye ? -3.8 : -4.8);
  662.     if (rotatepipes)
  663.         glRotatef(initial_rotation, 0.0, 1.0, 0.0);
  664.  
  665.     //glScalef(Scale4Iconic, Scale4Iconic, Scale4Iconic);
  666.     glScalef(Scale4Window, Scale4Window, Scale4Window);
  667.     
  668.  
  669.     FindNeighbors();
  670.  
  671.     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, system_color);
  672.  
  673.     /* If it's the begining of a system, draw a sphere */
  674.     if (olddir == dirNone) {
  675.         glPushMatrix();
  676.         glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0);
  677.         mySphere(0.6);
  678.         glPopMatrix();
  679.     }
  680.     /* Check for stop conditions */
  681.     if (ndirections == 0 || counter > system_length) {
  682.         glPushMatrix();
  683.         glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0);
  684.         /* Finish the system with another sphere */
  685.         mySphere(0.6);
  686.         glPopMatrix();
  687.  
  688.         /* If the maximum number of system was drawn, restart (clearing the screen), */
  689.         /* else start a new system. */
  690.         if (++system_number > number_of_systems) {
  691.             (void) sleep(1);
  692.             pinit( 1);
  693.         } else {
  694.             pinit(0);
  695.         }
  696.  
  697.         glPopMatrix();
  698.         //glFlush();
  699.         return;
  700.     }
  701.     counter++;
  702.     turncounter++;
  703.  
  704.     /* Do will the direction change? if so, determine the new one */
  705.     newdir = nowdir;
  706.     if (!directions[newdir]) {    /* cannot proceed in the current direction */
  707.         newdir = SelectNeighbor();
  708.     } else {
  709.         if (tightturns) {
  710.             /* random change (20% chance) */
  711.             if ((counter > 1) && (NRAND_PIPES(100) < 20)) {
  712.                 newdir = SelectNeighbor();
  713.             }
  714.         } else {
  715.             /* Chance to turn increases after each length of pipe drawn */
  716.             if ((counter > 1) && NRAND_PIPES(50) < NRAND_PIPES(turncounter + 1)) {
  717.                 newdir = SelectNeighbor();
  718.                 turncounter = 0;
  719.             }
  720.         }
  721.     }
  722.  
  723.     /* Has the direction changed? */
  724.     if (newdir == nowdir) {
  725.         /* If not, draw the cell's center pipe */
  726.         glPushMatrix();
  727.         glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0);
  728.         /* Chance of factory shape here, if enabled. */
  729.         if ((counter > 1) && (NRAND_PIPES(100) < factory)) {
  730.             MakeShape(newdir);
  731.         } else {
  732.             MakeTube(newdir);
  733.         }
  734.         glPopMatrix();
  735.         //glFlush();
  736.     } else {
  737.         /* If so, draw the cell's center elbow/sphere */
  738.         int         sysT = system_type;
  739.  
  740.         if (sysT == NofSysTypes + 1) {
  741.             sysT = ((system_number - 1) % NofSysTypes) + 1;
  742.         }
  743.         glPushMatrix();
  744.  
  745.         switch (sysT) {
  746.             case 1:
  747.                 glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0);
  748.                 mySphere(elbowradius);
  749.                 break;
  750.             case 2:
  751.             case 3:
  752.                 switch (nowdir) {
  753.                     case dirUP:
  754.                         switch (newdir) {
  755.                             case dirLEFT:
  756.                                 glTranslatef((PX - 16) / 3.0 * 4.0 - (one_third), (PY - 12) / 3.0 * 4.0 - (one_third), (PZ - 16) / 3.0 * 4.0);
  757.                                 glRotatef(180.0, 1.0, 0.0, 0.0);
  758.                                 break;
  759.                             case dirRIGHT:
  760.                                 glTranslatef((PX - 16) / 3.0 * 4.0 + (one_third), (PY - 12) / 3.0 * 4.0 - (one_third), (PZ - 16) / 3.0 * 4.0);
  761.                                 glRotatef(180.0, 1.0, 0.0, 0.0);
  762.                                 glRotatef(180.0, 0.0, 1.0, 0.0);
  763.                                 break;
  764.                             case dirFAR:
  765.                                 glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0 - (one_third), (PZ - 16) / 3.0 * 4.0 - (one_third));
  766.                                 glRotatef(90.0, 0.0, 1.0, 0.0);
  767.                                 glRotatef(180.0, 0.0, 0.0, 1.0);
  768.                                 break;
  769.                             case dirNEAR:
  770.                                 glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0 - (one_third), (PZ - 16) / 3.0 * 4.0 + (one_third));
  771.                                 glRotatef(90.0, 0.0, 1.0, 0.0);
  772.                                 glRotatef(180.0, 1.0, 0.0, 0.0);
  773.                                 break;
  774.                         }
  775.                         break;
  776.                     case dirDOWN:
  777.                         switch (newdir) {
  778.                             case dirLEFT:
  779.                                 glTranslatef((PX - 16) / 3.0 * 4.0 - (one_third), (PY - 12) / 3.0 * 4.0 + (one_third), (PZ - 16) / 3.0 * 4.0);
  780.                                 break;
  781.                             case dirRIGHT:
  782.                                 glTranslatef((PX - 16) / 3.0 * 4.0 + (one_third), (PY - 12) / 3.0 * 4.0 + (one_third), (PZ - 16) / 3.0 * 4.0);
  783.                                 glRotatef(180.0, 0.0, 1.0, 0.0);
  784.                                 break;
  785.                             case dirFAR:
  786.                                 glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0 + (one_third), (PZ - 16) / 3.0 * 4.0 - (one_third));
  787.                                 glRotatef(270.0, 0.0, 1.0, 0.0);
  788.                                 break;
  789.                             case dirNEAR:
  790.                                 glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0 + (one_third), (PZ - 16) / 3.0 * 4.0 + (one_third));
  791.                                 glRotatef(90.0, 0.0, 1.0, 0.0);
  792.                                 break;
  793.                         }
  794.                         break;
  795.                     case dirLEFT:
  796.                         switch (newdir) {
  797.                             case dirUP:
  798.                                 glTranslatef((PX - 16) / 3.0 * 4.0 + (one_third), (PY - 12) / 3.0 * 4.0 + (one_third), (PZ - 16) / 3.0 * 4.0);
  799.                                 glRotatef(180.0, 0.0, 1.0, 0.0);
  800.                                 break;
  801.                             case dirDOWN:
  802.                                 glTranslatef((PX - 16) / 3.0 * 4.0 + (one_third), (PY - 12) / 3.0 * 4.0 - (one_third), (PZ - 16) / 3.0 * 4.0);
  803.                                 glRotatef(180.0, 1.0, 0.0, 0.0);
  804.                                 glRotatef(180.0, 0.0, 1.0, 0.0);
  805.                                 break;
  806.                             case dirFAR:
  807.                                 glTranslatef((PX - 16) / 3.0 * 4.0 + (one_third), (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0 - (one_third));
  808.                                 glRotatef(270.0, 1.0, 0.0, 0.0);
  809.                                 glRotatef(180.0, 0.0, 1.0, 0.0);
  810.                                 break;
  811.                             case dirNEAR:
  812.                                 glTranslatef((PX - 16) / 3.0 * 4.0 + (one_third), (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0 + (one_third));
  813.                                 glRotatef(270.0, 1.0, 0.0, 0.0);
  814.                                 glRotatef(180.0, 0.0, 0.0, 1.0);
  815.                                 break;
  816.                         }
  817.                         break;
  818.                     case dirRIGHT:
  819.                         switch (newdir) {
  820.                             case dirUP:
  821.                                 glTranslatef((PX - 16) / 3.0 * 4.0 - (one_third), (PY - 12) / 3.0 * 4.0 + (one_third), (PZ - 16) / 3.0 * 4.0);
  822.                                 break;
  823.                             case dirDOWN:
  824.                                 glTranslatef((PX - 16) / 3.0 * 4.0 - (one_third), (PY - 12) / 3.0 * 4.0 - (one_third), (PZ - 16) / 3.0 * 4.0);
  825.                                 glRotatef(180.0, 1.0, 0.0, 0.0);
  826.                                 break;
  827.                             case dirFAR:
  828.                                 glTranslatef((PX - 16) / 3.0 * 4.0 - (one_third), (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0 - (one_third));
  829.                                 glRotatef(270.0, 1.0, 0.0, 0.0);
  830.                                 break;
  831.                             case dirNEAR:
  832.                                 glTranslatef((PX - 16) / 3.0 * 4.0 - (one_third), (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0 + (one_third));
  833.                                 glRotatef(90.0, 1.0, 0.0, 0.0);
  834.                                 break;
  835.                         }
  836.                         break;
  837.                     case dirNEAR:
  838.                         switch (newdir) {
  839.                             case dirLEFT:
  840.                                 glTranslatef((PX - 16) / 3.0 * 4.0 - (one_third), (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0 - (one_third));
  841.                                 glRotatef(270.0, 1.0, 0.0, 0.0);
  842.                                 break;
  843.                             case dirRIGHT:
  844.                                 glTranslatef((PX - 16) / 3.0 * 4.0 + (one_third), (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0 - (one_third));
  845.                                 glRotatef(270.0, 1.0, 0.0, 0.0);
  846.                                 glRotatef(180.0, 0.0, 1.0, 0.0);
  847.                                 break;
  848.                             case dirUP:
  849.                                 glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0 + (one_third), (PZ - 16) / 3.0 * 4.0 - (one_third));
  850.                                 glRotatef(270.0, 0.0, 1.0, 0.0);
  851.                                 break;
  852.                             case dirDOWN:
  853.                                 glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0 - (one_third), (PZ - 16) / 3.0 * 4.0 - (one_third));
  854.                                 glRotatef(90.0, 0.0, 1.0, 0.0);
  855.                                 glRotatef(180.0, 0.0, 0.0, 1.0);
  856.                                 break;
  857.                         }
  858.                         break;
  859.                     case dirFAR:
  860.                         switch (newdir) {
  861.                             case dirUP:
  862.                                 glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0 + (one_third), (PZ - 16) / 3.0 * 4.0 + (one_third));
  863.                                 glRotatef(90.0, 0.0, 1.0, 0.0);
  864.                                 break;
  865.                             case dirDOWN:
  866.                                 glTranslatef((PX - 16) / 3.0 * 4.0, (PY - 12) / 3.0 * 4.0 - (one_third), (PZ - 16) / 3.0 * 4.0 + (one_third));
  867.                                 glRotatef(90.0, 0.0, 1.0, 0.0);
  868.                                 glRotatef(180.0, 1.0, 0.0, 0.0);
  869.                                 break;
  870.                             case dirLEFT:
  871.                                 glTranslatef((PX - 16) / 3.0 * 4.0 - (one_third), (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0 + (one_third));
  872.                                 glRotatef(90.0, 1.0, 0.0, 0.0);
  873.                                 break;
  874.                             case dirRIGHT:
  875.                                 glTranslatef((PX - 16) / 3.0 * 4.0 + (one_third), (PY - 12) / 3.0 * 4.0, (PZ - 16) / 3.0 * 4.0 + (one_third));
  876.                                 glRotatef(270.0, 1.0, 0.0, 0.0);
  877.                                 glRotatef(180.0, 0.0, 0.0, 1.0);
  878.                                 break;
  879.                         }
  880.                         break;
  881.                 }
  882.                 myElbow((sysT == 2));
  883.                 break;
  884.         }
  885.         glPopMatrix();
  886.     }
  887.  
  888.     OPX = PX;
  889.     OPY = PY;
  890.     OPZ = PZ;
  891.     olddir = nowdir;
  892.     nowdir = newdir;
  893.     switch (nowdir) {
  894.         case dirUP:
  895.             PY++;
  896.             break;
  897.         case dirDOWN:
  898.             PY--;
  899.             break;
  900.         case dirLEFT:
  901.             PX--;
  902.             break;
  903.         case dirRIGHT:
  904.             PX++;
  905.             break;
  906.         case dirNEAR:
  907.             PZ++;
  908.             break;
  909.         case dirFAR:
  910.             PZ--;
  911.             break;
  912.     }
  913.     Cells[PX][PY][PZ] = 1;
  914.  
  915.     /* Cells'face pipe */
  916.     glTranslatef(((PX + OPX) / 2.0 - 16) / 3.0 * 4.0, ((PY + OPY) / 2.0 - 12) / 3.0 * 4.0, ((PZ + OPZ) / 2.0 - 16) / 3.0 * 4.0);
  917.     MakeTube(newdir);
  918.  
  919.     glPopMatrix();
  920.  
  921.     glFlush();
  922.  
  923. }
  924.  
  925. void
  926. change_pipes()
  927. {
  928.  
  929.     pinit(1);
  930. }
  931.  
  932. void
  933. release_pipes()
  934. {
  935.  
  936.                 /* Display lists MUST be freed while their glXContext is current. */
  937.  
  938.                 if (valve)
  939.                     glDeleteLists(valve, 1);
  940.                 if (bolts)
  941.                     glDeleteLists(bolts, 1);
  942.                 if (betweenbolts)
  943.                     glDeleteLists(betweenbolts, 1);
  944.  
  945.                 if (elbowbolts)
  946.                     glDeleteLists(elbowbolts, 1);
  947.                 if (elbowcoins)
  948.                     glDeleteLists(elbowcoins, 1);
  949.  
  950.                 if (guagehead)
  951.                     glDeleteLists(guagehead, 1);
  952.                 if (guageface)
  953.                     glDeleteLists(guageface, 1);
  954.                 if (guagedial)
  955.                     glDeleteLists(guagedial, 1);
  956.                 if (guageconnector)
  957.                     glDeleteLists(guageconnector, 1);
  958.  
  959. }